#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/usb.h>

/*******************************************************************************
* proto
*******************************************************************************/

int buzzbox_probe(struct usb_interface *,const struct usb_device_id *);
void buzzbox_disconnect(struct usb_interface *);
static int buzzbox_open(struct inode * i, struct file * f);
static int buzzbox_release(struct inode * i, struct file * f);
static ssize_t buzzbox_read(struct file * f, char __user * buf, size_t len, loff_t * off);
static ssize_t buzzbox_write(struct file * f, const char __user * buf, size_t len, loff_t * off);
	


/*******************************************************************************
* usb device
*******************************************************************************/
struct s_usb_buzzbox
{
  struct usb_device     *udev;
  struct usb_interface  *interface;
};

static struct s_usb_buzzbox usb_buzzbox;
static unsigned char usb_buffer[512];

static struct usb_device_id buzzbox_id[]=
{
  {USB_DEVICE(0x23f1,0x6734)},
  {}
};

static struct usb_driver buzzbox_driver =
{
  .name       = "buzzbox",
  .id_table   = buzzbox_id,
  .probe      = buzzbox_probe,
  .disconnect = buzzbox_disconnect 
};

/*
f65172c0 237416882 S Ci:2:009:0 s 80 06 0100 0000 0012 18 <
f65172c0 237416992 C Ci:2:009:0 0 18 = 12010002 ffffff40 f1233467 00010102 0301
    BDTCTRL 00080034 COUNT=008 UOWN=0 DATA0/1=0 PID=d  (SETUP)                  
    bmRequestType  80                                                           
    bRequest       06                                                           
    wValue         0100                                                         
    wIndex         0000                                                         
    wLength        0012                                                         
    GET_DESCRIPTOR/DEVICE                                                       
USB: IRQ TRN                                                                    
    U1IR    =2c                                                                 
    U1EIR   =00                                                                 
    U1STAT  =0c  ENDPT=0  DIR=1  PPBI=1                                         
    BDTCTRL 00120064 COUNT=012 UOWN=0 DATA0/1=1 PID=9  (IN)                     
USB: IRQ TRN                                                                    
    U1IR    =2c                                                                 
    U1EIR   =00                                                                 
    U1STAT  =00  ENDPT=0  DIR=0  PPBI=0                                         
    BDTCTRL 00000044 COUNT=000 UOWN=0 DATA0/1=1 PID=1  (OUT)                    
*/

int buzzbox_probe(struct usb_interface *intf,const struct usb_device_id *id)
{
  printk(KERN_ALERT "buzzbox_probe:\n");  

  usb_buzzbox.udev      = interface_to_usbdev(intf); 
  usb_buzzbox.interface = intf;
  
  //usb_register_dev(intf, &usb_buzzbox);
  
  return 0;
}

void buzzbox_disconnect(struct usb_interface *intf)
{

  return;
}

/*******************************************************************************
* character device
*******************************************************************************/
struct file_operations buzzbox_fops= 
{
  .owner   = THIS_MODULE,
  .read    = buzzbox_read,
  .write   = buzzbox_write,
  .open    = buzzbox_open,
  .release = buzzbox_release,
};


static int buzzbox_open(struct inode * i, struct file * f)
{
  int status;
  printk(KERN_ALERT "buzzbox_open\n");
  
  status = usb_control_msg(usb_buzzbox.udev,
             usb_rcvctrlpipe(usb_buzzbox.udev, 0),
             0x06,
             0x80,
             0x0100,
             0x0000,
             usb_buffer,
             18,
             HZ * 5);
 
  printk(KERN_ALERT "  status = %d\n",status);  
  return 0;
}

static int buzzbox_release(struct inode * i, struct file * f)
{
  printk(KERN_ALERT "buzzbox_release\n");
  return 0;
}

static ssize_t buzzbox_read(struct file * f, char __user * buf, size_t len, loff_t * off)
{
  printk(KERN_ALERT "buzzbox_read\n");
  return 0;
}

static ssize_t buzzbox_write(struct file * f, const char __user * buf, size_t len, loff_t * off)
{
  printk(KERN_ALERT "buzzbox_write\n");
  return 0;
}

/*******************************************************************************
* buzzbox_init
* buzzbox_exit
*******************************************************************************/
static int __init buzzbox_init(void)
{
  int status;
  
  printk(KERN_ALERT "buzzbox_init:\n");
  
  /* register a character device */
  status = register_chrdev(200,"buzzbox",&buzzbox_fops);
  if(status<0) return status;
  
  printk(KERN_ALERT "buzzbox_init: load module\n");
  status = usb_register(&buzzbox_driver);
  if(status)
    printk(KERN_ALERT "buzzbox: usb_register failed (%d)\n",status);
  return status;

  return 0;
  
}

static void __exit buzzbox_exit(void)
{
  printk(KERN_ALERT "buzzbox_exit: unload module\n");
  usb_deregister(&buzzbox_driver);
  
  unregister_chrdev(200,"buzzbox");
  
}

/*******************************************************************************
*
*******************************************************************************/
module_init(buzzbox_init);
module_exit(buzzbox_exit);

MODULE_LICENSE("GPL");
